TL;DR

You may click on the following links to fast forward to the codes directly producing the Figures:

Back to index page.

About this Vignette

This vignette illustrates the label transfer strategy in the original publication (Lin et al., 2022), with which the transcriptome states were evaluated for AAV transduced / untransduced / LPS-primed microglia. The strategy is largely inspired by Seurat Multimodal reference mapping vignette and Mapping and annotating query datasets vignette from Satija group.

The input files of this vignette are processed h5Seurat objects, produced by the preprocessing vignettes (see index page). The output is a Seurat object merging both query and reference data in the .h5Seurat format.

Analysis Outline

Upstream analysis pipelines (i.e. sequence alignment, generation of digital expression matrix, etc.):

  • For Smart-seq2, fastq files were processed by a custom Snakemake workflow to generate the expression table (feature-barcode-count matrix).
  • For 10X, fastq files from 3 mice were quantified by CellRanger (v6.0.1) using cellranger count and then aggregated using cellranger aggr.

Downstream analysis:

  • Preprocessing and QC (scater)
  • Seurat Standard Workflow (Seurat)
  • Label Transfer (Seurat)

Pre-processing

Load libraries and data

Load reuiqred libraries.

suppressPackageStartupMessages({
  library(Seurat)
  library(SeuratDisk)
  library(tidyverse)
  library(RColorBrewer)
})

Load the Seurat objects to workspace.

# Preprocessed, QCed Smart-seq2 microglia (Query dataset)
querydata <- LoadH5Seurat('../data/AAV_MG_scRNAseq/query_clean.h5Seurat', verbose = F)

# Preprocessed, QCed 10X (Reference dataset)
refdata <- LoadH5Seurat(file = '../data/AAV_MG_scRNAseq/refdata_clean.h5Seurat', verbose = F)
DimPlot(querydata, group.by = "treatment") | DimPlot(refdata, group.by = "treat")

Label transfer to identify cell states

We use Seurat to jointly analyze the query dataset (Smart-seq2) and reference dataset (10X).
Specifically, the 10X reference was created with controlled experiments of three treatment groups: Saline, 10 mg/kg Poly(i:c) and 0.83mg/kg LPS (administered i.p.). This provides us with a high quality “mini-atlas” of microglia under healthy (Saline) and immune-active (Poly(i:c) and LPS) states.

By leveraging the “microglia state” information in the reference dataset, we applied the Seurat anchor method to transfer the “state” labels from the reference to the query dataset. In doing so, we are able to make predictions about the state of the microglia in the query, as shown below.

Find anchors between reference and query.

dims_use <- 1:45

anchors <- FindTransferAnchors(
  reference = refdata,
  query = querydata,
  k.filter = 50,
  normalization.method = "LogNormalize",
  reference.reduction = "pca",
  dims = dims_use
)

Project query onto the reference UMAP structure.

refdata <- RunUMAP(refdata, dims = dims_use, reduction.name = "umap", seed.use = 42, return.model = TRUE)

query.transferred <- MapQuery(
  anchorset = anchors,
  query = querydata,
  reference = refdata,
  refdata = list(
    state = "state",
    treat = "treat"
  ),
  reference.reduction = "pca",
  reduction.model = "umap"
)

Queried cells with predictions score lower than 0.8 are probably incorrect (Stuart et al., 20191, Fig.3D). In our analysis, we see only a small fraction of cells with low prediction scores. We speculate that these cells might represent low quality cells and thus they are filtered out. Once this is done, the reference and query objects are merged into a single object called refquery.

query.transferred <- SetIdent(query.transferred, cells = WhichCells(query.transferred, expression = predicted.treat.score < 0.8), value = "low")
query.transferred <- SetIdent(query.transferred, cells = WhichCells(query.transferred, expression = predicted.treat.score >= 0.8), value = "high")
query.transferred$score <- Idents(query.transferred)

query.transferred[[c("predicted.treat.score","score")]] %>%
  ggplot(aes(x = predicted.treat.score, fill = score)) + 
  geom_histogram(bins = 20, color = "#333333") +
  coord_flip() +
  theme_light()

query.transferred.filtered <- subset(query.transferred, subset = predicted.treat.score > 0.8)
query.transferred.filtered$score <- NULL

## Merge objects
refquery <- merge(refdata, query.transferred.filtered)

Computing a ‘de novo’ UMAP visualization

According to the Multimodal reference mapping vignette, query cells directly mapping to the reference-derived UMAP will project to the most similar cells in the reference, which can potentially mask the presence of query cell types or cell states not captured in the reference. To account for these caveats, it is important to compute a ‘de novo’ UMAP visualization on the merged dataset during biological interpretation. Here we perform the computation and show that microglia from our query does not develop novel states which are absent in the reference.

refquery[['pca']] <- merge(refdata[['pca']], query.transferred.filtered[['ref.pca']])
refquery <- RunUMAP(refquery, reduction = "pca", dims = 1:45, n.epochs = 600)
DimPlot(refquery, group.by = "id") | DimPlot(refquery, group.by = "treat")

Brief Conclusion

The label transfer and its related stratigies2 3 4 5 have been used extensively to predict cell types across different experiment batches and modalities.
Here, we showcase an alternative application where the state of the transcriptome of individual cells can be predicted with a good quality reference generated by tailored experiment designs. Combined with prior knowledge from cell biology, this strategy can be a powerful device in field such as immunology and neurobiology, where the profiling of cell states (i.e. diseased-vs-healthy) may provide insights of the biological system under study.

Update Metadata

aav <- WhichCells(query.transferred, expression = treatment %in% c("AAV-MG1.2","AAV-MG1.1"))
lps <- WhichCells(query.transferred, expression = treatment == "LPS")
Idents(refquery) <- "treat"
refquery <- SetIdent(refquery, cells = aav, value = "AAV transduction")
refquery <- SetIdent(refquery, cells = lps, value = "LPS (Query)")
refquery[["treat"]] <- Idents(refquery)

Idents(refquery) <- "state"
hom_pred <- WhichCells(query.transferred, expression = predicted.state == "Homeostatic")
reac_pred <- WhichCells(query.transferred, expression = predicted.state == "Reactive")
refquery <- SetIdent(refquery, cells = hom_pred, value = "Homeostatic (Predicted)")
refquery <- SetIdent(refquery, cells = reac_pred, value = "Reactive (Predicted)")
refquery[["state"]] <- Idents(refquery)

transduced <- WhichCells(querydata, expression = mScarlet > 0)
non_transduced <- WhichCells(querydata, expression = mScarlet == 0)
q_lps <- WhichCells(query.transferred.filtered, expression = treatment == "LPS")
Idents(refquery) <- "treat"
refquery <- SetIdent(refquery, cells = transduced, value = "Transduced")
refquery <- SetIdent(refquery, cells = non_transduced, value = "Untransduced")
refquery <- SetIdent(refquery, cells = q_lps, value = "LPS(Query)")
refquery[["ident"]] <- Idents(refquery)

Idents(query.transferred.filtered) <- "transduction"
query.transferred.filtered <- SetIdent(query.transferred.filtered, cells = q_lps, value = "LPS(Query)")
query.transferred.filtered[["ident"]] <- Idents(query.transferred.filtered)
query.transferred.filtered$ident <- as.character(query.transferred.filtered$ident)

Reproducing Plots

Extended Data Figure 2i

refquery$id <- factor(refquery$id, levels = c("Reference","Query"))
as.data.frame(refquery[[c("nCount_RNA","nFeature_RNA","id")]]) %>%
  ggplot(mapping = aes(x=id, y=nCount_RNA)) +
  geom_violin() +
  geom_jitter(aes(color = id), size = 0.3, height = 0, width = 0.3) +
  scale_x_discrete(labels = c("Reference\n(10x)","Query\n(Smart-seq2)")) +
  scale_y_continuous(expand = c(0.1,0.1)) +
  xlab(NULL) +
  ylab("UMI counts") +
  theme_linedraw() +
  theme(
    legend.position = "none",
    axis.text.x = element_text(size = 16),
    axis.text.y = element_text(size = 14),
    axis.title.y =  element_text(size = 18)
    )

Extended Data Figure 2j

as.data.frame(refquery[[c("nFeature_RNA","id")]]) %>%
  ggplot(mapping = aes(x=id, y=nFeature_RNA)) +
  geom_violin() +
  geom_jitter(aes(color = id), size = 0.3, height = 0, width = 0.3) +
  scale_x_discrete(labels = c("Reference\n(10x)","Query\n(Smart-seq2)")) +
  scale_y_continuous(expand = c(0.1,0.1)) +
  xlab(NULL) +
  ylab("Genes Detected") +
  theme_linedraw() +
  theme(
    legend.position = "none",
    axis.text.x = element_text(size = 16),
    axis.text.y = element_text(size = 14),
    axis.title.y =  element_text(size = 18)
    )

DEG analysis and marker expressions

Extended Data Figure 2k

Identify differentially expression genes (DEGs).

Idents(refdata) <- "treat"
mks.refdata.all <- FindAllMarkers(refdata, only.pos = T)

Idents(query.transferred.filtered) <- "group"
mks.querydata.all <- FindAllMarkers(query.transferred.filtered, only.pos = T)

Parse DEGs.

mkset.1 <- intersect(mks.refdata.all[mks.refdata.all$cluster == "Saline",]$gene, 
                     mks.querydata.all[mks.querydata.all$cluster == "AAV",]$gene)

mkset.2 <- mks.refdata.all[mks.refdata.all$cluster == "Poly(i:c)",]$gene

mkset.3 <- intersect(mks.refdata.all[mks.refdata.all$cluster %in% c("LPS","Poly(i:c)"),]$gene, 
                     mks.querydata.all[mks.querydata.all$cluster == "LPS",]$gene)

DEGs Heatmap

Preparing for heatmap plot.

refdata$treat <- factor(refdata$treat, levels = c("Saline","Poly(i:c)","LPS"))
refdata <- ScaleData(refdata, features = c(mkset.1, mkset.2, mkset.3, VariableFeatures(refdata)))

Heatmap of DEGs in Saline, Poly(i:c), LPS groups in reference dataset.

## Downsample for demo
DoHeatmap(subset(refdata, downsample = 500),
          features = c(mkset.1, mkset.2, mkset.3),
          group.by = "treat",
          group.colors = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
  scale_fill_distiller(palette = "RdBu") +
  theme(
    axis.text.y = element_blank()
    )

## Extremely slow, could crash Rstudio. Only run on high performance work-stations or clusters.
# DoHeatmap(refdata,
#           features = c(mkset.1, mkset.2, mkset.3),
#           group.by = "treat",
#           group.colors = brewer.pal(n = 12, name = "Paired")[c(1,3,5)],
#           label = FALSE) +
#   scale_fill_distiller(palette = "RdBu") +
#   theme(
#     axis.text.y = element_blank()
#     ) +
#   NoLegend()

Violin plots for Representative Genes

Idents(refdata) <- "treat"
features_hom = c("P2ry12","Cx3cr1","Sall1")
features_hom_lab = c( "Csf1r")

vplots = list()
for (feature in features_hom){
  vplots[[feature]] <- FetchData(refdata, vars = c("treat", feature)) %>% 
    ggplot(aes_string(x = "treat", y = feature)) + 
    geom_violin(aes_string(fill = "treat")) + 
    geom_jitter(aes_string(color = "treat"), size = 0.3, alpha = 0.2, width = 0.25) + 
    scale_color_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
    scale_fill_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
    theme_classic() +
    theme(
      legend.position = "none",
      axis.title.x = element_blank(),
      axis.text.x = element_blank(),
      axis.title.y = element_text(size = 16, family = "Arial"),
      axis.text.y = element_text(size = 12, family = "Arial")
    )
}

for (feature in features_hom_lab){
  vplots[[feature]] <- FetchData(refdata, vars = c("treat", feature)) %>% 
    ggplot(aes_string(x = "treat", y = feature)) + 
    geom_violin(aes_string(fill = "treat")) + 
    geom_jitter(aes_string(color = "treat"), size = 0.3, alpha = 0.2, width = 0.25) + 
    scale_color_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
    scale_fill_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
    theme_classic() +
    theme(
      legend.position = "none",
      axis.title.x = element_blank(),
      axis.text.x = element_text(size = 15, family = "Arial"),
      axis.title.y = element_text(size = 16, family = "Arial"),
      axis.text.y = element_text(size = 12, family = "Arial")
    )
}
vplots[["P2ry12"]] / vplots[["Cx3cr1"]] / vplots[["Sall1"]] / vplots[["Csf1r"]]

features_rea = c("Il1b","Spp1","Ifitm3")
features_rea_lab = c("Ccl5")

vplots = list()
for (feature in features_rea){
  vplots[[feature]] <- FetchData(refdata, vars = c("treat", feature)) %>% 
    ggplot(aes_string(x = "treat", y = feature)) + 
    geom_violin(aes_string(fill = "treat")) + 
    geom_jitter(aes_string(color = "treat"), size = 0.3, alpha = 0.2, width = 0.25) + 
    scale_color_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
    scale_fill_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
    theme_classic() +
    theme(
      legend.position = "none",
      axis.title.x = element_blank(),
      axis.text.x = element_blank(),
      axis.title.y = element_text(size = 16, family = "Arial"),
      axis.text.y = element_text(size = 12, family = "Arial")
    )
}

for (feature in features_rea_lab){
  vplots[[feature]] <- FetchData(refdata, vars = c("treat", feature)) %>% 
    ggplot(aes_string(x = "treat", y = feature)) + 
    geom_violin(aes_string(fill = "treat")) + 
    geom_jitter(aes_string(color = "treat"), size = 0.3, alpha = 0.2, width = 0.25) + 
    scale_color_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
    scale_fill_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,3,5)]) +
    theme_classic() +
    theme(
      legend.position = "none",
      axis.title.x = element_blank(),
      axis.text.x = element_text(size = 15, family = "Arial"),
      axis.title.y = element_text(size = 16, family = "Arial"),
      axis.text.y = element_text(size = 12, family = "Arial")
    )
}
vplots[["Il1b"]] / vplots[["Spp1"]] / vplots[["Ifitm3"]] / vplots[["Ccl5"]]

Extended Data Figure 2l

DEGs Heatmap

Preparing for heatmap plot.

query.transferred.filtered$ident <- factor(query.transferred.filtered$ident, levels = c("Untransduced","Transduced","LPS(Query)"))
query.transferred.filtered <- ScaleData(query.transferred.filtered, features = c(mkset.1, mkset.2, mkset.3, VariableFeatures(query.transferred.filtered)))

Heatmap of DEGs in AAV, LPS groups in query dataset.

## Demo
DoHeatmap(query.transferred.filtered,
          features = c(mkset.1,mkset.3),
          group.by = "ident",
          group.colors = brewer.pal(n = 12, name = "Paired")[c(1,8,6)]) +
  theme(
    axis.text.y = element_blank()
    ) +
  scale_fill_distiller(palette = "PiYG")

# DoHeatmap(query.transferred.filtered,
#           features = c(mkset.1,mkset.3),
#           group.by = "ident",
#           group.colors = brewer.pal(n = 12, name = "Paired")[c(1,8,6)],
#           label = FALSE) +
#   theme(
#     axis.text.y = element_blank()
#     ) +
#   scale_fill_distiller(palette = "PiYG") +
#   NoLegend()

Violin plots for Representative Genes

Idents(query.transferred.filtered) <- "ident"
features_hom = c("P2ry12","Cx3cr1","Sall1")
features_hom_lab = c( "Csf1r")

vplots = list()
for (feature in features_hom){
  vplots[[feature]] <- FetchData(query.transferred.filtered, vars = c("treatment", feature)) %>% 
    ggplot(aes_string(x = "treatment", y = feature)) + 
    geom_jitter(aes_string(color = "treatment"), size = 0.6, alpha = 1, width = 0.25) + 
    geom_violin(aes_string(fill = "treatment"), alpha = 0.6) + 
    scale_color_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,7,5)]) +
    scale_fill_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,7,5)]) +
    theme_classic() +
    theme(
      legend.position = "none",
      axis.title.x = element_blank(),
      axis.text.x = element_blank(),
      axis.title.y = element_text(size = 16, family = "Arial"),
      axis.text.y = element_text(size = 12, family = "Arial")
    )
}

for (feature in features_hom_lab){
  vplots[[feature]] <- FetchData(query.transferred.filtered, vars = c("treatment", feature)) %>% 
    ggplot(aes_string(x = "treatment", y = feature)) + 
    geom_jitter(aes_string(color = "treatment"), size = 0.6, alpha = 1, width = 0.25) + 
    geom_violin(aes_string(fill = "treatment"), alpha = 0.6) + 
    scale_color_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,7,5)]) +
    scale_fill_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,7,5)]) +
    scale_x_discrete(labels = c("Untransd.","Transd.","LPS")) +
    theme_classic() +
    theme(
      legend.position = "none",
      axis.title.x = element_blank(),
      axis.text.x = element_text(size = 15, family = "Arial"),
      axis.title.y = element_text(size = 16, family = "Arial"),
      axis.text.y = element_text(size = 12, family = "Arial")
    )
}
vplots[["P2ry12"]] / vplots[["Cx3cr1"]] / vplots[["Sall1"]] / vplots[["Csf1r"]]

features_rea = c("Il1b","Spp1","Ifitm3")
features_rea_lab = c("Ccl5")

vplots = list()
for (feature in features_rea){
  vplots[[feature]] <- FetchData(query.transferred.filtered, vars = c("treatment", feature)) %>% 
    ggplot(aes_string(x = "treatment", y = feature)) + 
    geom_jitter(aes_string(color = "treatment"), size = 0.6, alpha = 1, width = 0.25) + 
    geom_violin(aes_string(fill = "treatment"), alpha = 0.6) + 
    scale_color_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,7,5)]) +
    scale_fill_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,7,5)]) +
    theme_classic() +
    theme(
      legend.position = "none",
      axis.title.x = element_blank(),
      axis.text.x = element_blank(),
      axis.title.y = element_text(size = 16, family = "Arial"),
      axis.text.y = element_text(size = 12)
    )
}

for (feature in features_rea_lab){
  vplots[[feature]] <- FetchData(query.transferred.filtered, vars = c("treatment", feature)) %>% 
    ggplot(aes_string(x = "treatment", y = feature)) + 
    geom_jitter(aes_string(color = "treatment"), size = 0.6, alpha = 1, width = 0.25) + 
    geom_violin(aes_string(fill = "treatment"), alpha = 0.6) + 
    scale_color_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,7,5)]) +
    scale_fill_manual(values = brewer.pal(n = 12, name = "Paired")[c(1,7,5)]) +
    scale_x_discrete(labels = c("Untransd.","Transd.","LPS")) +
    theme_classic() +
    theme(
      legend.position = "none",
      axis.title.x = element_blank(),
      axis.text.x = element_text(size = 15, family = "Arial"),
      axis.title.y = element_text(size = 16, family = "Arial"),
      axis.text.y = element_text(size = 12, family = "Arial")
    )
}
vplots[["Il1b"]] / vplots[["Spp1"]] / vplots[["Ifitm3"]] / vplots[["Ccl5"]]

Save Results

Backup the processed Seurat object using h5 format.

## Avoid using factor while saving to other formats
refquery$treat <- as.character(refquery$treat)
refquery$state <- as.character(refquery$state)
refquery$ident <- as.character(refquery$ident)

if(!dir.exists('../data/AAV_MG_scRNAseq')){dir.create('../data/AAV_MG_scRNAseq')}
SaveH5Seurat(refquery, filename = '../data/AAV_MG_scRNAseq/refquery.h5Seurat', overwrite = T, verbose = F)
SaveH5Seurat(query.transferred.filtered, filename = '../data/AAV_MG_scRNAseq/query_transferred.h5Seurat', overwrite = T, verbose = F)
Convert('../data/AAV_MG_scRNAseq/query_transferred.h5Seurat', dest = "h5ad", overwrite = T, verbose = F)

Session info

sessionInfo()
## R version 4.0.5 (2021-03-31)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.4 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=zh_CN.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=zh_CN.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=zh_CN.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=zh_CN.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] RColorBrewer_1.1-3    forcats_0.5.1         stringr_1.4.0        
##  [4] dplyr_1.0.9           purrr_0.3.4           readr_2.1.2          
##  [7] tidyr_1.2.0           tibble_3.1.7          ggplot2_3.3.6        
## [10] tidyverse_1.3.1       SeuratDisk_0.0.0.9020 sp_1.5-0             
## [13] SeuratObject_4.1.0    Seurat_4.1.1         
## 
## loaded via a namespace (and not attached):
##   [1] readxl_1.4.0          backports_1.4.1       plyr_1.8.7           
##   [4] igraph_1.3.2          lazyeval_0.2.2        splines_4.0.5        
##   [7] listenv_0.8.0         scattermore_0.8       digest_0.6.29        
##  [10] htmltools_0.5.2       fansi_1.0.3           magrittr_2.0.3       
##  [13] tensor_1.5            cluster_2.1.3         ROCR_1.0-11          
##  [16] limma_3.46.0          tzdb_0.3.0            globals_0.15.0       
##  [19] modelr_0.1.8          matrixStats_0.62.0    spatstat.sparse_2.1-1
##  [22] colorspace_2.0-3      rvest_1.0.2           ggrepel_0.9.1        
##  [25] haven_2.5.0           xfun_0.31             crayon_1.5.1         
##  [28] jsonlite_1.8.0        progressr_0.10.1      spatstat.data_2.2-0  
##  [31] survival_3.3-1        zoo_1.8-10            glue_1.6.2           
##  [34] polyclip_1.10-0       gtable_0.3.0          leiden_0.4.2         
##  [37] future.apply_1.9.0    abind_1.4-5           scales_1.2.0         
##  [40] DBI_1.1.2             spatstat.random_2.2-0 miniUI_0.1.1.1       
##  [43] Rcpp_1.0.8.3          viridisLite_0.4.0     xtable_1.8-4         
##  [46] reticulate_1.25       spatstat.core_2.4-4   bit_4.0.4            
##  [49] htmlwidgets_1.5.4     httr_1.4.3            ellipsis_0.3.2       
##  [52] ica_1.0-2             farver_2.1.0          pkgconfig_2.0.3      
##  [55] sass_0.4.1            uwot_0.1.11           dbplyr_2.2.0         
##  [58] deldir_1.0-6          utf8_1.2.2            labeling_0.4.2       
##  [61] tidyselect_1.1.2      rlang_1.0.2           reshape2_1.4.4       
##  [64] later_1.3.0           munsell_0.5.0         cellranger_1.1.0     
##  [67] tools_4.0.5           cli_3.3.0             generics_0.1.2       
##  [70] broom_0.8.0           ggridges_0.5.3        evaluate_0.15        
##  [73] fastmap_1.1.0         yaml_2.3.5            goftest_1.2-3        
##  [76] fs_1.5.2              knitr_1.39            bit64_4.0.5          
##  [79] fitdistrplus_1.1-8    RANN_2.6.1            pbapply_1.5-0        
##  [82] future_1.26.1         nlme_3.1-158          mime_0.12            
##  [85] xml2_1.3.3            hdf5r_1.3.5           compiler_4.0.5       
##  [88] rstudioapi_0.13       plotly_4.10.0         png_0.1-7            
##  [91] spatstat.utils_2.3-1  reprex_2.0.1          bslib_0.3.1          
##  [94] stringi_1.7.6         highr_0.9             RSpectra_0.16-1      
##  [97] rgeos_0.5-9           lattice_0.20-45       Matrix_1.4-1         
## [100] vctrs_0.4.1           pillar_1.7.0          lifecycle_1.0.1      
## [103] spatstat.geom_2.4-0   lmtest_0.9-40         jquerylib_0.1.4      
## [106] RcppAnnoy_0.0.19      data.table_1.14.2     cowplot_1.1.1        
## [109] irlba_2.3.5           httpuv_1.6.5          patchwork_1.1.1      
## [112] R6_2.5.1              promises_1.2.0.1      KernSmooth_2.23-20   
## [115] gridExtra_2.3         parallelly_1.32.0     codetools_0.2-18     
## [118] MASS_7.3-57           assertthat_0.2.1      withr_2.5.0          
## [121] sctransform_0.3.3     mgcv_1.8-40           parallel_4.0.5       
## [124] hms_1.1.1             grid_4.0.5            rpart_4.1-15         
## [127] rmarkdown_2.14        Rtsne_0.16            shiny_1.7.1          
## [130] lubridate_1.8.0

  1. Stuart, T. et al. Comprehensive Integration of Single-Cell Data. Cell 177, 1888-1902.e21 (2019).↩︎

  2. Kiselev, V. Y., Yiu, A. & Hemberg, M. scmap: projection of single-cell RNA-seq data across data sets. Nat Methods 15, 359–362 (2018).↩︎

  3. Srivastava, D., Iyer, A., Kumar, V. & Sengupta, D. CellAtlasSearch: a scalable search engine for single cells. Nucleic Acids Research 46, W141–W147 (2018).↩︎

  4. Sato, K., Tsuyuzaki, K., Shimizu, K. & Nikaido, I. CellFishing.jl: an ultrafast and scalable cell search method for single-cell RNA sequencing. Genome Biology 20, 31 (2019).↩︎

  5. Cao, Z.-J., Wei, L., Lu, S., Yang, D.-C. & Gao, G. Searching large-scale scRNA-seq databases via unbiased cell embedding with Cell BLAST. Nat Commun 11, 3458 (2020).↩︎